package blackjack.client;

import java.net.*;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.io.*;
import java.util.*;

import javax.swing.ImageIcon;
import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;




@SuppressWarnings("serial")
public class Client extends JApplet{

	private int cWidth = 200;
	private int cHeight = 200;
	private int gWidth = 600;
	private int gHeight = 350;

	private int firstleft = 0;
	private int secondleft = 0;
	private int param = 0;
	private int param2 = 0;
	private int points = 0;

	private String kokku = null;
	private String name = null;
	private String first = null;
	private String second = null;

	CardDeck cardDeck = new CardDeck();

	@SuppressWarnings("unchecked")
	ArrayList esimeneKard = new ArrayList();
	@SuppressWarnings("unchecked")
	ArrayList teineKard = new ArrayList();
	@SuppressWarnings("unchecked")
	ArrayList textfieds = new ArrayList();
	@SuppressWarnings("unchecked")
	ArrayList pickedCards= new ArrayList();

	JLabel r = new JLabel();
	JLabel info = new JLabel();
	JLabel kasutajaviga = new JLabel("Unustasite kasutajanimi");

	JTextField saatmine = new JTextField(15);

	JPanel bottomPanel = new JPanel();

	JButton getCard = new JButton(""); 
	JButton newGame = new JButton(""); 
	JButton quit = new JButton("");
	JButton enough = new JButton("");
	JButton connect = new JButton("");

	Font f = new Font(null, Font.ITALIC, 15);

	private Socket socket;

	private BufferedReader in;
	private PrintWriter out = null;

	Container cp = getContentPane();

	DrawPanel botPanel = new DrawPanel();
	DrawPanel1 mainPanel = new DrawPanel1();
	topPanel topPanel = new topPanel();


	public void init() {
		ImageIcon connectImg1 = new ImageIcon("images/connect1.jpg");

		connect.setIcon(connectImg1);

		connect.addMouseMotionListener(new MouseMotionListener() {

			@Override
			public void mouseMoved(MouseEvent arg0) {
				ImageIcon connectImg2 = new ImageIcon("images/connect2.png");
				connect = new JButton(connectImg2);
			}

			@Override
			public void mouseDragged(MouseEvent arg0) {
				ImageIcon connectImg2 = new ImageIcon("images/connect2.png");
				connect = new JButton(connectImg2);
			}
		});

		this.setSize(cWidth, cHeight);
		newGame.setEnabled(false);
		mainPanel.setLayout(new FlowLayout());
		botPanel.setLayout(new FlowLayout());
		getCard.setEnabled(false);
		enough.setEnabled(false);

		getCard.setVisible(false);
		enough.setVisible(false);
		newGame.setVisible(false);
		quit.setVisible(false);

		/*TOP panel BUTTONS*/
		topPanel.add(getCard);
		topPanel.add(enough);
		topPanel.add(newGame);
		topPanel.add(quit);

		cp.add(BorderLayout.NORTH, topPanel);
		cp.add(BorderLayout.CENTER, mainPanel);

		botPanel.add(r);
		botPanel.add(saatmine);
		botPanel.add(connect);
		cp.add(BorderLayout.CENTER, botPanel);
		connect.addActionListener(botPanel);
		getCard.addActionListener(mainPanel);

		quit.addActionListener( new ActionListener(){
			public void actionPerformed(ActionEvent e){
				System.exit(0);
			}
		});

		newGame.addActionListener( new ActionListener(){
			public void actionPerformed(ActionEvent e){
				kokku = null;		param = 0;
				first = null;		param2 = 0;
				second = null;		points = 0;
				firstleft = 0;	secondleft = 0;

				esimeneKard.clear();	getCard.setEnabled(true);
				teineKard.clear();		enough.setEnabled(true);
				textfieds.clear();		mainPanel.repaint();
				pickedCards.clear();
			}
		});

		enough.addActionListener( new ActionListener(){
			public void actionPerformed(ActionEvent e){
				sendMessage("enough");
				getCard.setEnabled(false);
				enough.setEnabled(false);
			}
		});
	}

	//topPanel
	class topPanel extends DrawPanel implements Runnable {}

	/**
	 * Connection Panel 
	 */
	class DrawPanel extends JPanel implements ActionListener, Runnable{
		String nimi;
		Thread t;

		public DrawPanel(){
			init();
			t = new Thread(this);
		}

		public void init(){
			setBackground(Color.BLACK);
		}

		/**
		 * gets Typed Name
		 */
		@Override
		public void actionPerformed(ActionEvent arg0) {
			if(saatmine.getText().length() > 0){
				t.start();
				nimi = saatmine.getText();
			}
		}

		public void run(){
			while(true){
				InetAddress addr = null;

				try {
					getCard.setEnabled(true);
					enough.setEnabled(true);
					addr = InetAddress.getByName("localhost");
				} catch (UnknownHostException e1) {
					e1.printStackTrace();
				}
				try {
					socket = new Socket(addr, 8888); // JutuServer, PORT
				} catch (IOException e) {
					System.out.println("No connection to the server");
					return;
				}
				try {
					connected();
					cp.add(BorderLayout.CENTER, mainPanel);
					System.out.println("socket = " + socket);
					try {
						in = new BufferedReader(new InputStreamReader(socket
								.getInputStream()));

					} catch (IOException e) {
						e.printStackTrace();
					}

					try {
						out = new PrintWriter(new BufferedWriter(
								new OutputStreamWriter(socket.getOutputStream())), true);
						name = nimi;
						out.println(nimi);
					} catch (IOException e) {
						e.printStackTrace();
					}
					BufferedReader in = new BufferedReader(new InputStreamReader(System.in));

					Listener l = new Listener();
					l.start();

					String s = null;

					do {
						try {
							s = in.readLine();
						} catch (IOException e) {
							e.printStackTrace();
						} // blocked...
						if (s.length() > 0) out.println(s); // send message toServer
					}
					while (!s.equals("END")); // END do 
				} 
				finally {
					System.out.println("close...");
					try {
						socket.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}

	/**
	 * painting getCard
	 */
	public class DrawPanel1 extends JPanel implements ActionListener{
		String winner = "WINNER !!!";
		String looser = "LOOSER";
		FontMetrics fontMetrics = getFontMetrics(new Font(null, Font.ITALIC, 20));
		int looserWidth = fontMetrics.stringWidth(looser);
		int winnerWidth = fontMetrics.stringWidth(winner);

		Image myCards;
		Image backgr;

		public void actionPerformed(ActionEvent arg0) {
			newGame.setEnabled(false);
			if(points < 22) out.println("getCard");
			Graphics g = getGraphics();
			paintComponent(g);
		}

		public void paintComponent(Graphics g) {
			super.paintComponent(g);
			backgr = Toolkit.getDefaultToolkit().getImage ("images/background.jpg");
			g.drawImage(backgr, 0, 0, getWidth(), getHeight(),null);
			
			createIcons();
			
			int kokku1 = 0;
			int kokku2 = 0;

			for(int y = 0; y < pickedCards.size(); y++){
				myCards =  Toolkit.getDefaultToolkit().getImage ("images/" + pickedCards.get(y) + ".jpg");
				g.drawImage(myCards, y*60, getHeight()/2, this);
			}
			//imja odnogo
			if(first != null) {
				FontMetrics fontMetrics = getFontMetrics(f);
				int width = fontMetrics.stringWidth(first);

				g.setFont(f);
				g.setColor(Color.CYAN);
				g.drawString(first, getWidth() - width, 15);
			}
			for(int z = 0; z < esimeneKard.size(); z++){
				if(param != 0){
					kokku1 += cardDeck.CardStringtoInt((String) esimeneKard.get(z));//s4itaet o4ki sopernika
				}
			}
			//risuet points odnogo
			if(param != 0){
				FontMetrics fontMetrics = getFontMetrics(f);
				String k1 = (Integer.toString(kokku1));
				int width = fontMetrics.stringWidth(k1 + "-");
				int width1 = fontMetrics.stringWidth(first);
				g.setFont(f);
				g.setColor(Color.CYAN);
				g.drawString(k1 + "-", getWidth() - width - width1, 15);
			}

			for(int z = 0; z < teineKard.size(); z++){
				if(param2 != 0){
					kokku2 += cardDeck.CardStringtoInt((String) teineKard.get(z));
				}
			}
			//pointq i imja drugogo
			if(param2 != 0){
				FontMetrics fontMetrics = getFontMetrics(f);
				int width = fontMetrics.stringWidth(Integer.toString(kokku2)+ "-" + second);
				g.drawString((Integer.toString(kokku2)+ "-" + second), getWidth() - width, 30);
			}
			
			//risuet pointq
			drawPoints(g);
			
			if(firstleft != 0 && secondleft != 0){
				drawWinner(g);
				getCard.setEnabled(false);
				enough.setEnabled(false);
				newGame.setEnabled(true);
			}
			if(kokku != null && kokku.equals(2) == true && (firstleft != 0 || secondleft != 0)){
				drawWinner(g);
			}
			if((param != 0 || param2 != 0) ){
				if(points <= 21){
					if((kokku1 > points || kokku2 > points) && kokku1 <= 21 && kokku2 <= 21){
						drawLooser(g);
					}
					if(points > kokku1 && points > kokku2 && kokku1 < 21 && kokku2 <= 21){
						drawWinner(g);
					}
					if(points == kokku1 && kokku1 <= 21 && kokku2 <= 21 && kokku1 > kokku2){
						drawWinner(g);
					}
					if(points == kokku2 && kokku2 <= 21 && kokku1 <= 21 && kokku2 > kokku1){
						drawWinner(g);
					}
					if(points > kokku2 && kokku1 > 21 && kokku2 <= 21){
						drawWinner(g);
					}
				}
				if(points < 21){
					if(points>kokku1 && kokku1 <= 21 && kokku2 > 21){
						drawWinner(g);
					}
					if(kokku1 > 21 && kokku2 > 21){
						drawWinner(g);
					}
				}
				if(points > 21){
					if(kokku1 > 21){
						if(kokku2 > 21){
							String s = "NO WINNERS, JUST LOOSERS";
							int drawWidth = fontMetrics.stringWidth(s);
							g.drawString(s, getWidth() - drawWidth, getHeight()/3);
						}
						if(kokku2 <= 21){
							drawLooser(g);
						}
					}
					if(kokku1 <= 21){
						if(kokku2 > 21){
							drawLooser(g);
						}
						if(kokku2 == 0){
							drawLooser(g);
						}
						if(kokku1 == 0){
							drawLooser(g);
						}
					}
				}
				if(points == kokku1 && kokku1 == kokku2){
					drawWinner(g);
				}
				if(points != 0 && kokku1 == kokku2 && kokku2 == 0){
					drawWinner(g);
				}
			}
		}

		//buttons beautiful
		private void createIcons() {
			ImageIcon newGameImg1 = new ImageIcon("images/newgame1.png");
			ImageIcon enough1 = new ImageIcon("images/enough1.png");
			ImageIcon quit1 = new ImageIcon("images/quit1.png");
			ImageIcon getcards1 = new ImageIcon("images/getcards1.png");
			
			newGame.setIcon(newGameImg1);

			enough.setIcon(enough1);
			quit.setIcon(quit1);
			getCard.setIcon(getcards1);
		}
		
		//draws looser msg
		private void drawLooser(Graphics g) {
			g.drawString(looser, getWidth() - looserWidth, getHeight()/3);
		}

		//draws winner msg
		private void drawWinner(Graphics g) {
			g.drawString(winner, getWidth() - winnerWidth, getHeight()/3);
		}

		/**
		 * draws currentPlayer's points
		 * @param g
		 */
		private void drawPoints(Graphics g) {
			int height = 18;
			Font f = new Font(null, Font.ITALIC, height);
			g.setFont(f);
			g.setColor(Color.CYAN);
			g.drawString("Points : " + Integer.toString(points), 0, getHeight()/2 - height);
		}
	}

	/**
	 * waits messages fromServer and does relevant actions
	 *
	 */
	class Listener extends Thread {
		@SuppressWarnings("unchecked")
		public void run() {
			try {
				while (true) { // main tsqkl
					String str = in.readLine(); // blocked...

					mainPanel.repaint();
					allClients(str);
					othersCards(str);

					if(str!= null && opgCard(str)!= null) {
						if(who(str).equals(first) && who(str) != null){
							esimeneKard.add("deck");
						}
						if(who(str).equals(second) && who(str) != null){
							teineKard.add("deck");
						}
					}
					error(str);
					if(Character.isDigit(str.charAt(0)) == true) {
						pickedCards.add(str);
						points += cardDeck.CardStringtoInt(str);
					}
				} // while
			} catch (IOException e) {
			} finally {
				try {
					if (!socket.isClosed()) {
						socket.close();
						System.out.println("closed...");
						return;
					}
				} catch (IOException ee) {
				}
			} // finally
		}

		/**
		 * who left
		 * @param str  fromserver string
		 */
		public void error(String str){
			String[] temp = null;

			temp = str.split(" ");

			for(int i = 0; i < temp.length ; i++){
				if(temp[i].equals(name))break;
				if(temp[i].equals("-avarii...")){
					if(temp[i-1].equals(first)){
						esimeneKard.clear();
						first += " left the game ";
						firstleft++;
					}
					if(temp[i-1].equals(second)){
						teineKard.clear();
						second += " left the game ";
						secondleft++;
					}
					continue;
				}
			}
		}

		/**
		 * 
		 * @param str - fromServer
		 * @return someone picked a card?
		 */
		public String who(String str){
			String who = null;
			String[] temp = null;
			String delimeter = " ";

			temp = str.split(delimeter);

			for(int i =0; i < temp.length ; i++){
				if(temp[i].equals(name))break;
				if(temp[i].equals(first))who = first;
				if(temp[i].equals(second))who = second;
			}
			return who;
		}// run

		/**
		 * Mitu kasutajat tuli mangu
		 * @param str fromServer
		 */
		public void allClients(String str){
			String[] temp = null;
			temp = str.split(" ");
			for(int i =0; i < temp.length ; i++){
				if(temp[i].equals(name))break;
				if(temp[i].equals("kokku")){
					kokku = temp[i-1];
					continue;
				}
			}
		}

		/**
		 * Uute kasutajate kohta info leidmine
		 * @param str - fromServer string
		 * @return
		 */
		public String opgCard(String str){
			String res = null;
			String[] temp = null;
			temp = str.split(" ");
			for(int i =0; i < temp.length ; i++){
				if(temp[i].equals(name))break;
				if(temp[i].equals("says:")){
					if(first == null){
						first = temp[i-1];
					}
					if(second == null){
						if(first.equals(temp[i-1]) == false){
							second = temp[i-1];
						}
					}
				}
			}
			return res;
		}

		/**
		 * share cards info
		 * @param str fromServer
		 */
		@SuppressWarnings("unchecked")
		public void othersCards(String str){
			int d = 0;
			int d2 = 0;

			String[] temp = null;
			temp = str.split(" ");

			for(int i =0; i < temp.length ; i++){
				if(temp[i].equals(name))break;

				if(temp[i].equals("all")){
					if(temp[i-1].equals(first)){
						d++;
						esimeneKard.clear();
						param++;
					}
					if(temp[i-1].equals(second)){
						d2++;
						teineKard.clear();
						param2++;
					}
					continue;
				}
				if(d != 0)esimeneKard.add(temp[i]);
				if(d2 != 0)teineKard.add(temp[i]);
			}
			if(d != 0 || d2 != 0)newGame.setEnabled(true);
		}
	}

	/**
	 * To send a message
	 * @param message
	 */
	public void sendMessage(String message){
		out.println(message);
	}

	public void connected() {
		this.setSize(gWidth, gHeight);
		botPanel.setVisible(false);
		connect.setEnabled(false);
		getCard.setVisible(true);
		enough.setVisible(true);
		newGame.setVisible(true);
		quit.setVisible(true);
	}

}
